/**
 * 
 */
package traj.dataset;

import java.awt.geom.Point2D;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Random;

import qmo.geometry.Location;
import traj.core.Params;
import traj.dataset.QmoMessage.Behavior;
import traj.dataset.QmoMessage.EntityType;

/**
 * To generate NBG or TPL dataset in a uniform distribution.
 * 
 * @author xiaohui
 * 
 */
public class UniformGenerator {

	final static int MIN_UPDATES = 5;
	final static int MAX_UPDATES = 10;
	final static float MIN_SPEED = 50; // km/h
	final static float MAX_SPEED = 150; // km/h
	final static int[] roads = { 1, 2, 3, 4, 5, 6 };
	final static int numPt = 3;
	final static int idFrom = 1;

	Random rdm = null;
	double xmax, ymax;

	public UniformGenerator(long seed, double xmax, double ymax) {
		this.rdm = new Random(seed);
		this.xmax = xmax;
		this.ymax = ymax;
	}

	public Point2D.Double getOne() {
		double x = this.rdm.nextDouble() * xmax;
		double y = this.rdm.nextDouble() * ymax;

		// a little format
		double x1 = (int) (x * 100) / 100.0;
		double y1 = (int) (y * 100) / 100.0;
		return new Point2D.Double(x1, y1);
	}

	/**
	 * public static void genTplDataset(long seed, double xmax, double ymax, int
	 * num, int idFrom, String filePath) { UniformGenerator ug = new
	 * UniformGenerator(seed, xmax, ymax); try { BufferedWriter bw = new
	 * BufferedWriter(new FileWriter(filePath)); int i = 0; while (i < num) {
	 * Point2D.Double p = ug.getOne(); int id = idFrom + i; double x = (int)
	 * (p.x * 100) / 100.0; double y = (int) (p.y * 100) / 100.0; QmoMessage msg
	 * = new QmoMessage(EntityType.OBJECT, Behavior.APPE, id, 0, new Location(x,
	 * y)); bw.write(msg.toTplString() + "\n"); i++; } bw.flush(); bw.close(); }
	 * catch (IOException e) { System.out.println(e); System.exit(-1); }
	 * System.out.println("done!"); }
	 */

	/**
	 * public static void genNBGDataset(long seed, double xmax, double ymax, int
	 * num, int idFrom, String filePath) { UniformGenerator ug = new
	 * UniformGenerator(seed, xmax, ymax); try { BufferedWriter bw = new
	 * BufferedWriter(new FileWriter(filePath)); int i = 0; while (i < num) {
	 * Point2D.Double p = ug.getOne(); int id = idFrom + i; double x = (int)
	 * (p.x * 100) / 100.0; double y = (int) (p.y * 100) / 100.0; QmoMessage msg
	 * = new QmoMessage(EntityType.OBJECT, Behavior.APPE, id, 0, new Location(x,
	 * y)); bw.write(msg.toNbgString() + "\n"); i++; } bw.flush(); bw.close(); }
	 * catch (IOException e) { System.out.println(e); System.exit(-1); }
	 * System.out.println("File successfully generated!\nCheck " + filePath); }
	 * /* /** This method generates similuated moving objects data.
	 * 
	 * @param seed
	 * @param xmax
	 * @param ymax
	 * @param numMO
	 *            The number of moving objects to be generated.
	 * @param idFrom
	 * @param filePath
	 * @param minUpdates
	 *            The minimum number of updates for every moving object.
	 * @param maxUpdates
	 *            The maximum number of updates for every moving object.
	 * 
	 */
	public static void genNBGDatasetWithUpdate(long seed, double xmax,
			double ymax, int numMO, int idFrom, String filePath,
			int minUpdates, int maxUpdates) {
		UniformGenerator ug = new UniformGenerator(seed, xmax, ymax);
		try {
			BufferedWriter bw = new BufferedWriter(new FileWriter(filePath));
			int i = 0;
			while (i < numMO) {
				Random myrandom = new Random();
				int numUpdates = myrandom.nextInt(maxUpdates - minUpdates)
						+ minUpdates;
				// Firstly generate a new object msg
				Point2D.Double p = ug.getOne();
				int roadid = ug.getRoadID();
				float speed = ug.getSpeed();
				// EntityType entityType, Behavior behavior, int id, double
				// timestamp, Location location, int roadID, float speed,
				// TPoint.Direction direction

				QmoMessage msg = new QmoMessage(EntityType.OBJECT,
						Behavior.APPEAR, idFrom + i, 0, new Location(p.getX(),
								p.getY()), roadid, speed,
						Params.defaultDirection);

				// QmoMessage msg = new QmoMessage(EntityType.OBJECT,
				// Behavior.APPE, i, 0, new Location(p.getX(), p.getY()),
				// roadid, speed, TPoint.Direction.UP);
				bw.write(msg.toNbgString());
				bw.newLine();

				// generate update msgs here
				for (int j = 1; j <= numUpdates; j++) {
					QmoMessage m = new QmoMessage(EntityType.OBJECT,
							Behavior.UPDATE, idFrom + i, j, new Location(ug
									.getOne().getX(), ug.getOne().getY()), ug
									.getRoadID(), ug.getSpeed(),
							Params.defaultDirection);
					bw.write(m.toNbgString());
					bw.newLine();
				}
				// Generate disappear msg
				QmoMessage m1 = new QmoMessage(EntityType.OBJECT,
						Behavior.DISAPPEAR, idFrom + i, numUpdates + 1,
						new Location(ug.getOne().getX(), ug.getOne().getY()),
						ug.getRoadID(), ug.getSpeed(), Params.defaultDirection);
				bw.write(m1.toNbgString());
				bw.newLine();
				i++;
			}
			bw.flush();
			bw.close();
		} catch (IOException e) {
			System.out.println(e);
			System.exit(-1);
		}
		System.out.println("File successfully generated!\nCheck " + filePath);
	}

	/**
	 * 
	 * @return randomly generated speed
	 */
	private float getSpeed() {
		Random myrandom = new Random();
		return MIN_SPEED + myrandom.nextInt((int) (MAX_SPEED - MIN_SPEED));
	}

	private int getRoadID() {
		Random myrandom = new Random();
		int index = myrandom.nextInt(roads.length);
		return roads[index];
	}

	// public static void main(String[] args) {
	// String usage = "Usage: seed xmax ymax num idFrom filePath";
	// if (args.length != 6) {
	// System.out.println(usage);
	// System.exit(-1);
	// } else {
	// long seed = Long.parseLong(args[0]);
	// double xmax = Double.parseDouble(args[1]);
	// double ymax = Double.parseDouble(args[2]);
	// int num = Integer.parseInt(args[3]);
	// int idFrom = Integer.parseInt(args[4]);
	// String filePath = args[5];
	// genNBGDataset(seed, xmax, ymax, num, idFrom, filePath);
	// }
	// }
	public static void main(String[] args) {
		long seed = 12345688;
		double x = 1000.0;
		double y = 1000.0;

		String file = "E:/Research/trajectory_indexing/data/uniform.dat";
		genNBGDatasetWithUpdate(seed, x, y, numPt, idFrom, file, MIN_UPDATES,
				MAX_UPDATES);
	}
}
